use std::collections::*;
use std::sync::Arc;

use super::map::WorldState;

/// Represents a slice of ticks of some arbitrary set of loaded chunks, keeping
/// most chunks in them the same.  Chunks that don't change between ticks should
/// refer to the same underlying [``ChunkState``] structure, reducing overall
/// memory footprint, but don't necessarily have to.
pub struct History {
    tick_states: BTreeMap<u64, Arc<WorldState>>,
}

impl History {
    /// Creates a new history tracker instance.
    pub fn new(tick_states: BTreeMap<u64, Arc<WorldState>>) -> Self {
        Self { tick_states }
    }

    /// Creates a new history tracker with a provided tick 0 state.
    pub fn create(base_state: Arc<WorldState>) -> Self {
        let mut states = BTreeMap::new();
        states.insert(0, base_state);
        Self::new(states)
    }

    pub fn oldest_tick(&self) -> u64 {
        *self.tick_states.first_key_value().unwrap().0
    }

    pub fn newest_tick(&self) -> u64 {
        *self.tick_states.last_key_value().unwrap().0
    }

    pub fn get_newest_state(&self) -> &Arc<WorldState> {
        self.tick_states.last_key_value().unwrap().1
    }

    /// Inserts a world state into the history if it does not exist.  Or if it
    /// does, returns the old copy.
    pub fn insert_tick(&mut self, tick: u64, ws: Arc<WorldState>) -> Option<Arc<WorldState>> {
        if let Some(exist) = self.tick_states.get(&tick) {
            return Some(exist.clone());
        }

        self.tick_states.insert(tick, ws);
        None
    }
}
